﻿using blackhouse.Data;
using blackhouse.NemoBlog.Business;
using blackhouse.NemoBlog.Business.Model;
using blackhouse.WebNemo.Business.Groups;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Runtime.Caching;
using System.Web;

namespace blackhouse.StareKino.Web.Events {
    public class CinemaPostListModel : IPostListModel {

        #region Fields

        private int placeId;
        private CinemaNemoBlogPosts posts;
        private AdoDataHelper dataHelper;
        private DateTime[] postDates;
        private int selectedYear = -1;
        private int selectedMonth = -1;

        #endregion

        #region Properties

        public int PlaceId {
            get {
                return this.placeId;
            }
            set {
                if (this.placeId != value) {
                    this.placeId = value;
                    this.posts = new CinemaNemoBlogPosts(this.placeId);
                }
            }
        }

        public int PostCountOnPage { get { return 10; } }

        private CinemaNemoBlogPosts Posts {
            get {
                if (this.posts == null)
                    throw new Exception("Lista postów jest niedostępna ponieważ nie ustawiono wartości dla PlaceId");
                return this.posts;
            }
        }

        internal int SelectedYear {
            get {
                if (this.selectedYear == -1) {
                    this.selectedYear = this.ParseParamFromRequest("y");
                    if (this.selectedYear > 0 && (this.selectedYear > DateTime.Now.Year || this.selectedYear < this.GetPostDates().Min().Year))
                        this.selectedYear = 0;
                }
                return this.selectedYear;
            }
        }

        internal int SelectedMonth {
            get {
                if (this.selectedMonth == -1) {
                    this.selectedMonth = this.ParseParamFromRequest("m");
                    if (this.selectedMonth > 0 && (this.selectedMonth < 1 || this.selectedMonth > 12))
                        this.selectedMonth = 0;
                }
                return this.selectedMonth;
            }
        }

        #endregion

        #region Constructors

        public CinemaPostListModel() {
            this.dataHelper = new MsSqlAdoDataHelper(ConfigurationManager.AppSettings["MSSQLConnectionString"]);
        }

        #endregion

        #region Methods

        private int ParseParamFromRequest(string pName) {
            if (HttpContext.Current == null) return -1;
            if (HttpContext.Current.Request == null) return -1;
            string sV = HttpContext.Current.Request.QueryString[pName];
            int v = 0;
            if (!String.IsNullOrEmpty(sV)
                && Int32.TryParse(sV, out v))
                return v;
            else
                return 0;
        }

        public NemoBlogPost[] GetLastPosts(int postCount, bool onlyPublished) {
            DateTime fromDate, toDate;
            if (this.TrimPublishedDateRange(out fromDate, out toDate))
                return this.Posts.GetLastPostsByEventDateRange(postCount, fromDate, toDate);
            else
                return this.Posts.GetLastPostsOrderByEventDate(postCount, onlyPublished);
        }

        public NemoBlogPost[] GetLastPosts(int lastPostId, int postCount, bool onlyPublished) {
            DateTime fromDate, toDate;
            if (this.TrimPublishedDateRange(out fromDate, out toDate))
                return this.Posts.GetLastPostsByEventDateRange(lastPostId, postCount, fromDate, toDate);
            else
                return this.Posts.GetLastPostsOrderByEventDate(lastPostId, postCount, onlyPublished);
        }

        public NemoBlogPost[] GetPostsByTag(NemoBlogTag tag, int postCount, bool onlyPublished) {
            return this.Posts.GetPostsByTag(tag.TagId, onlyPublished);
        }

        internal DateTime[] GetPostDates() {
            if (this.postDates != null) return this.postDates;
            if (MemoryCache.Default.Contains("PostDates-" + this.PlaceId)) {
                this.postDates = MemoryCache.Default["PostDates-" + this.PlaceId] as DateTime[];
                if (this.postDates != null) return this.postDates;
            }
            this.postDates = this.GetPostDatesFromDatabase();
            CacheItem ci = new CacheItem("PostDates-" + this.PlaceId, this.postDates);
            CacheItemPolicy cip = new CacheItemPolicy();
            cip.SlidingExpiration = TimeSpan.FromMinutes(20);
            IGroup postsGroup = blackhouse.WebNemo.Business.Factory.Instance().GetGroup("BLOG_POSTS");
            cip.ChangeMonitors.Add(new blackhouse.WebNemo.Data.Cache.NemoChangeMonitor(postsGroup.Id));
            MemoryCache.Default.Add(ci, cip);
            return this.postDates;
        }

        private DateTime[] GetPostDatesFromDatabase() {
            this.dataHelper.Reset();
            this.dataHelper.ProcedureName = "bhp_NemoBlogPosts_GetDates";
            this.dataHelper.AddParameter("ModuleId", this.PlaceId, DbType.Int32);
            IDataReader reader = this.dataHelper.Execute();
            List<DateTime> dates = new List<DateTime>();
            while (reader.Read()) {
                dates.Add(Convert.ToDateTime(reader[0]));
            }
            reader.Close();
            return dates.ToArray();
        }

        private bool TrimPublishedDateRange(out DateTime fromDate, out DateTime toDate) {
            if (this.SelectedYear == 0) {
                fromDate = DateTime.MinValue;
                toDate = DateTime.MaxValue;
                return false;
            }
            if (this.SelectedMonth == 0) { // cały rok
                fromDate = new DateTime(this.SelectedYear, 1, 1);
                toDate = fromDate.AddYears(1).AddSeconds(-1);
            }
            else { // jeden miesiąc
                fromDate = new DateTime(this.SelectedYear, this.SelectedMonth, 1);
                toDate = fromDate.AddMonths(1).AddSeconds(-1);
            }
            return true;
        }

        #endregion

    }
}